﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using CcrFlows.Core;
using Microsoft.Ccr.Core;

namespace SampleFlow
{
    class Program_RearrangeTextFile
    {
        static void Main()
        {
            Console.WriteLine("Rearrange words in text file (Ctrl-C to exit)\n");

            while (true)
            {
                Console.Write("number of chars per output line: ");
                int maxLineLen = int.Parse(Console.ReadLine());

                Console.Write("output filename: ");
                string outputFilename = Console.ReadLine();
                if (!outputFilename.ToLower().EndsWith(".txt")) outputFilename += ".txt";

                var flow = Flow<string>
                    .DoWithIterator<string>(SplitFileIntoLines)
                    .DoWithIterator<string>(SplitLineIntoWords)
                    .Do(new AssembleLineFromWords(maxLineLen))
                    .Do<bool>(new FileWriter(outputFilename).WriteLines);

                flow.Input.Post(@"..\..\shakespeare.txt");

                flow.Receive(x => Process.Start("notepad.exe", outputFilename));
            }
        }

        static IEnumerator<string> SplitFileIntoLines(string filename)
        {
            using(StreamReader sr = new StreamReader(filename))
            {
                while(!sr.EndOfStream)
                    yield return sr.ReadLine();
                yield return null;
            }
        }

        static IEnumerator<string> SplitLineIntoWords(string line)
        {
            if (line != null)
                foreach (string word in line.Split(' '))
                    yield return word;
            else
                yield return null;
        }
    }


    class FileWriter
    {
        private readonly StreamWriter sw;

        public FileWriter(string filename)
        {
            this.sw = new StreamWriter(filename);
        }


        #region Implementation of ISeqHandler<string,bool>

        public void WriteLines(string line, Port<bool> output)
        {
            if (line != null)
            {
                this.sw.WriteLine(line);
            }
            else
            {
                this.sw.Close();
                output.Post(true);
            }
        }

        #endregion
    }
}
